package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSearchDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import com.tianji.learning.service.ILearningLessonService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author dayu
 * @since 2024-08-25
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
  private final UserClient userClient;
  private final InteractionReplyMapper replyMapper;
  private final SearchClient searchClient;
  private final CourseClient courseClient;
  private final CatalogueClient catalogueClient;
  private final CategoryCache categoryCache;

  @Override
  public void saveQuestion(QuestionFormDTO questionDTO) {
    Long userId = UserContext.getUser();
    InteractionQuestion interactionQuestion = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
    interactionQuestion.setUserId(userId);
    save(interactionQuestion);
  }

  @Override
  public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
    // 1.参数校验，课程id和小节id不能都为空
    Long courseId = query.getCourseId();
    Long sectionId = query.getSectionId();
    if (courseId == null && sectionId == null) {
      throw new BadRequestException("课程id和小节id不能都为空");
    }
    Page<InteractionQuestion> questionPage = this.lambdaQuery()
            .select(InteractionQuestion.class, info -> !info.getProperty().equals("description"))
            .eq(query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
            .eq(courseId != null, InteractionQuestion::getCourseId, query.getCourseId())
            .eq(sectionId != null, InteractionQuestion::getSectionId, query.getSectionId())
            .eq(InteractionQuestion::getHidden, false)
            .orderByDesc(InteractionQuestion::getCreateTime)
            .page(query.toMpPageDefaultSortByCreateTimeDesc());
    if (ObjectUtil.isEmpty(questionPage)) {
      return PageDTO.empty(questionPage);
    }
    List<InteractionQuestion> records = questionPage.getRecords();
    List<QuestionVO> questionVOList = new ArrayList<>();

    // 获取 userIdS 过滤匿名用户
    Set<Long> userIds = records.stream().filter(info -> !info.getAnonymity()).map(InteractionQuestion::getUserId).collect(Collectors.toSet());
    // 获取 lastAnswerIds 过滤匿名用户
    Set<Long> lastAnswerIds = records.stream().filter(info -> !info.getAnonymity()).map(InteractionQuestion::getLatestAnswerId).collect(Collectors.toSet());

    // 根据lastAnswerIds查询回答者信息
    Map<Long, InteractionReply> lastReplyMap = new HashMap<>(lastAnswerIds.size());
    if (ObjectUtils.isNotEmpty(userIds)) {
      List<InteractionReply> lastReplyList = replyMapper.selectBatchIds(lastAnswerIds);
      if (ObjectUtils.isNotEmpty(lastReplyList)) {
        for (InteractionReply reply : lastReplyList) {
          lastReplyMap.put(reply.getId(), reply);
          if (!reply.getAnonymity()) {
            // 收集最后一次回答者信息
            userIds.add(reply.getUserId());
          }
        }
      }
    }
    // 根据userid 查询回答者信息
    Map<Long, UserDTO> userInfoMap = new HashMap<>(userIds.size());
    if (ObjectUtils.isNotEmpty(userIds)) {
      List<UserDTO> userDTOList = userClient.queryUserByIds(userIds);
      // 转map  {userId:userInfo}
      if (ObjectUtils.isNotEmpty(userDTOList)) {
        userInfoMap = userDTOList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
      }
    }
    for (InteractionQuestion info : records) {
      QuestionVO vo = BeanUtil.copyProperties(info, QuestionVO.class);
      if (!info.getAnonymity()) {
        UserDTO userInfo = userInfoMap.get(info.getUserId());
        if (ObjectUtils.isNotEmpty(userInfo)) {
          vo.setUserName(userInfo.getName());
          vo.setUserIcon(userInfo.getIcon());
        }
      }

      // 根据last_answer_id 查询最后一个回答者信息
      if (ObjectUtil.isNotEmpty(info.getLatestAnswerId())) {
        InteractionReply lastReply = lastReplyMap.get(info.getLatestAnswerId());
        if (ObjectUtils.isEmpty(lastReply)) {
          continue;
        }
        vo.setLatestReplyContent(lastReply.getContent());
        if (!lastReply.getAnonymity()) {
          UserDTO userInfo = userInfoMap.get(lastReply.getUserId());
          if (ObjectUtils.isNotEmpty(userInfo)) {
            vo.setLatestReplyUser(userInfo.getName());
          }
        }
      }
      questionVOList.add(vo);
    }
    return PageDTO.of(questionPage, questionVOList);
  }

  @Override
  public QuestionVO getQuestionById(Long questionId) {
    InteractionQuestion question = getById(questionId);
    QuestionVO questionVO = BeanUtils.toBean(question, QuestionVO.class);
    UserDTO userDTO = userClient.queryUserById(question.getUserId());
    questionVO.setUserName(userDTO.getName());
    questionVO.setUserIcon(userDTO.getIcon());
    if (question.getAnonymity()) {
      questionVO.setUserName("");
      questionVO.setUserIcon("");
    }
    return questionVO;
  }

  @Override
  public void updateQuestion(Long questionId, @Valid QuestionFormDTO questionDTO) {
    InteractionQuestion question = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
    question.setId(questionId);
    updateById(question);
  }

  @Override
  public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
    // 1.处理课程名称，得到课程id
    List<Long> courseIds = null;
    if (ObjectUtils.isNotEmpty(query.getCourseName())) {
      courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
      if (CollUtils.isEmpty(courseIds)) {
        return PageDTO.empty(0L, 0L);
      }
    }
    // 2.分页查询
    Integer status = query.getStatus();
    LocalDateTime begin = query.getBeginTime();
    LocalDateTime end = query.getEndTime();
    Page<InteractionQuestion> page = lambdaQuery()
            .in(courseIds != null, InteractionQuestion::getCourseId, courseIds)
            .eq(status != null, InteractionQuestion::getStatus, status)
            .gt(begin != null, InteractionQuestion::getCreateTime, begin)
            .lt(end != null, InteractionQuestion::getCreateTime, end)
            .page(query.toMpPageDefaultSortByCreateTimeDesc());
    List<InteractionQuestion> records = page.getRecords();
    if (CollUtils.isEmpty(records)) {
      return PageDTO.empty(page);
    }

    // 3.准备VO需要的数据：用户数据、课程数据、章节数据
    Set<Long> userIds = new HashSet<>();
    Set<Long> cIds = new HashSet<>();
    Set<Long> cataIds = new HashSet<>();
    // 3.1.获取各种数据的id集合
    for (InteractionQuestion q : records) {
      userIds.add(q.getUserId());
      cIds.add(q.getCourseId());
      cataIds.add(q.getChapterId());
      cataIds.add(q.getSectionId());
    }
    // 3.2.根据id查询用户
    List<UserDTO> users = userClient.queryUserByIds(userIds);
    Map<Long, UserDTO> userMap = new HashMap<>(users.size());
    if (CollUtils.isNotEmpty(users)) {
      userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
    }

    // 3.3.根据id查询课程
    List<CourseSimpleInfoDTO> cInfos = courseClient.getSimpleInfoList(cIds);
    Map<Long, CourseSimpleInfoDTO> cInfoMap = new HashMap<>(cInfos.size());
    if (CollUtils.isNotEmpty(cInfos)) {
      cInfoMap = cInfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
    }

    // 3.4.根据id查询章节
    List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(cataIds);
    Map<Long, String> cataMap = new HashMap<>(catas.size());
    if (CollUtils.isNotEmpty(catas)) {
      cataMap = catas.stream()
              .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
    }


    // 4.封装VO
    List<QuestionAdminVO> voList = new ArrayList<>(records.size());
    for (InteractionQuestion q : records) {
      // 4.1.将PO转VO，属性拷贝
      QuestionAdminVO vo = BeanUtils.copyBean(q, QuestionAdminVO.class);
      voList.add(vo);
      // 4.2.用户信息
      UserDTO user = userMap.get(q.getUserId());
      if (user != null) {
        vo.setUserName(user.getName());
      }
      // 4.3.课程信息以及分类信息
      CourseSimpleInfoDTO cInfo = cInfoMap.get(q.getCourseId());
      if (cInfo != null) {
        vo.setCourseName(cInfo.getName());
        vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
      }
      // 4.4.章节信息
      vo.setChapterName(cataMap.getOrDefault(q.getChapterId(), ""));
      vo.setSectionName(cataMap.getOrDefault(q.getSectionId(), ""));
    }
    return PageDTO.of(page, voList);
  }

  @Override
  @Transactional
  public void delQuestionById(Long questionId) {
    // 判断是否是当前用户的问题
    InteractionQuestion question = getById(questionId);
    if (ObjectUtils.isEmpty(question)) {
      throw new BadRequestException("课程不存在");
    }
    LambdaQueryWrapper<InteractionReply> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(InteractionReply::getQuestionId, questionId);
    replyMapper.delete(queryWrapper);
    removeById(questionId);
  }

  @Override
  public void updateQuestionPageAdminHidden(Long questionId, boolean hidden) {
    lambdaUpdate().eq(InteractionQuestion::getId, questionId)
            .set(InteractionQuestion::getHidden, hidden)
            .update();
  }

  @Override
  public QuestionAdminVO getQuestionByIdInfo(Long questionId) {
    InteractionQuestion question = getById(questionId);
    if (ObjectUtils.isEmpty(question)) {
      throw new BadRequestException("问题不存在");
    }
    QuestionAdminVO questionAdminVO = BeanUtils.copyBean(question, QuestionAdminVO.class);
    // 根据课程id 查询课程教室负责人  查询课程老师表
    CourseSearchDTO searchInfo = courseClient.getSearchInfo(question.getCourseId());
    questionAdminVO.setTeacherName(userClient.queryUserById(searchInfo.getTeacher()).getName());
    // 获取三级分类
    questionAdminVO.setCategoryName(categoryCache.getCategoryNames(searchInfo.getCategoryIds()));

    //课程章章名称，节名称
    List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(List.of(question.getChapterId(), question.getSectionId()));
    for (CataSimpleInfoDTO cataSimpleInfoDTO : cataSimpleInfoDTOS) {
      if(cataSimpleInfoDTO.getId().equals(question.getSectionId())){
        questionAdminVO.setSectionName(cataSimpleInfoDTO.getName());
      }
      if(cataSimpleInfoDTO.getId().equals(question.getChapterId())){
        questionAdminVO.setChapterName(cataSimpleInfoDTO.getName());
      }
    }
    // 提问者信息
    UserDTO userDTO = userClient.queryUserById(question.getUserId());
    questionAdminVO.setUserName(userDTO.getName());
    questionAdminVO.setUserIcon(userDTO.getIcon());

    // 课程名称
    questionAdminVO.setCourseName(searchInfo.getName());
    // 问题修改为查看
    lambdaUpdate().eq(InteractionQuestion::getId, questionId)
            .set(InteractionQuestion::getStatus, 1)
            .update();
    return questionAdminVO;
  }
}
